home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Creative Computers
/
Creative Computers CD-ROM, Volume 1 (Legendary Design Technologies, Inc.)(1994).iso
/
text
/
misc
/
ctutor2.txt.pp
/
ctutor2.txt
Wrap
Text File
|
1994-11-17
|
13KB
|
299 lines
-surgery - Operations in "C"
-----------------------------
The C language was designed as a "middle level" language, that is a
language which lies somewhere between a high level language like BASIC and a
low level language like Assembler. This results in a language which is
harder to program in than basic, yet has features traditionally found only
in low level languages. Translation - Power, efficiency, speed etc. When
examining the operators in C it becomes very apparent that C is capable of
somethings that just don't exist in other languages.
Below is a table showing "C Precendence and Associativity". When
programming in C this can be of great help. All of the C operators in the
chart are explained below.
....Cut Here....Cut Here....Cut Here....Cut Here....Cut Here....
Category Assoc. Operators
primary ltor () [] . ->
secondary rtol * & ++ -- ~ ! - sizeof() (cast)
binary ltor * / %
+ -
<< >>
< > <= >=
== !=
&
^
|
&&
||
ternary rtol ?:
= += -= *= /= %= >>= <<= &= |=
comma ltor ,
Notes: Operators on same line have same precendence.
The operators ! < > <= >= == != && || are logical
operators.
....Cut Here....Cut Here....Cut Here....Cut Here....Cut Here....
So now we have a list of the operators available in C. All that remains
is to go through the list one by one and explain each ones use. Note: It
must be assumed that a basic knowledge of C data types exists or this
disscusion will fall short very quickly. Starting from the top, we can knock of the first level pretty quickly.
The () operators are used just as in regular math to ESTABLISH precedence.
That is to force the order of operations into a specific order. Items within
() are evaluated first. Next the square brakets [] are used in C as in
pascal and basic, to reference an array, so the fourth element in the array,
char letters[10];
We would reference letters[3] (note, ALL C arrays start at element 0, so
the array letters would have 10 elements numbered 0 through 9). So far so
simple. Next the . operator, this is refered to as the member operator and
is used to specify a specific memeber of a structure. For example using the
structure,
struct {
char number[13];
int unit;
char street[25];
} PhoneBook;
If we wanted the unit number of the record, we would reference it by
'PhoneBook.unit' similarly any of the other members could be referenced. In
C however structures are more often referenced by pointers. That is
'PhoneBook' in the above example was in fact declared as '*PhoneBook' then
in order to reference the member would be '(*PhoneBook).unit'. This is a
rather awkward thing to write, especially as it is such a common occourence
in C prpgramming. To alleviate this problem C provides the "Pointer"
operator. The above '(*PhoneBook).unit' can now be replaced by 'PhoneBook-
>unit' which translates to "PhoneBook pointing to the member unit".
That end the discussion of the primary operators. The next level of
operators are ones of the unary type. First however a quick review of
pointers.
A pointer is a variable which "points" to a value or group of values.
That is rather than storing the actual value in the variable, the variable
contains the memory location where the value can be found. This concept is
crucial to C for several very important reasons, and because of this several
C operators exist specifically to allow pointers to function. The first of
these has already been discussed, that is the '->' operator. The next is the
* operator. The * operator is used to declare a variable as a pointer as in,
char *ptr;
which declares a varibale 'ptr' which points to a character value. Also
the * operator tells C to take the value pointed to by a pointer, so if the
variable 'x' is declared as type char, then
x = *ptr;
will take the value pointed to by the pointer variable 'ptr', and stores
it in the variable 'x'. The next operator, &, does the exact opposite, that is it says return a
pointer to the given variable, so the line
ptr = &x;
would make the varibale 'ptr' point to the variable x. It is important
to realize the implications of this. So the following example is shown.
C Code x *ptr
int x=0; 0 ????
int *ptr; 0 ????
ptr = &x; 0 0
x = 5; 5 5
*ptr = 8; 8 8
x = x+2 10 10
The important idea here is that changes to one effect the other, note
that the ???? is because until the pointer is actually assigned, we have no
idea what it points to. For this reason the idea of a NULL pointer exists.
This is a pointer which points to nothing.
The next operators are the ++ and -- operators, they stand for increment
and decrement. These operators will increase or decrease the value of a
variable by 1 unit. They may be placed before or after the variable in
question as,
x++; /* post increment */
++x; /* pre increment */
The pre and post forms of these operators are important in that they
determine how a function will behave. For instance in,
b = 5;
a = b++;
'a' will recieve the value 5, while 'b' will have the value 6. This
is different from the code fragent,
b = 5;
a = ++b;
where both 'a' and 'b' have the value 6. The next operators of
importance are the - and ~ operators. The returns the "two's complement" or
negative value, while the second returns the "one's complement" or binary
negation. The effect of the negative operator is simple, 'a = -b' would
assign the negative of 'b' to 'a', however 'a = ~b' has a somewhat different
effect. If b = 5, and 'b' is a regular short integer, then the value of 'b'
in binary is, 0000 0101, and the value of ~b is 1111 1010. The exact binary
inverse of 'b'. There are two more operators of the unary type, the first is sizeof().
This returns the size, in bytes, of a data type. The result is evaluated at
compile time, and replaced by a literal, so sizeof(char) is 1 byte,
sizeof(SHORT) is 2, etc. This is especially useful when allocating memory
for a structure, ie
struct Window *win;
win = (struct Window *) malloc(sizeof(struct Window));
Ignoring most of the line, if a window structure requires 53 bytes, the
above line will return a pointer to an area of memory 53 bytes long, big
enough to store the information required by a window structure. The last
unary operator is the ! or 'not' operator. Quite simply it takes a true (ie
non-zero) result and makes it false (ie 0) or the opposite, so if a variable
'a' needs to be tested to see if it is zero, then the test 'if (!a)' will be
true if a is 0 and false otherwise. This is true also for pointers, a test
'if (!ptr)' will be true if the pointer evaluates to NULL, and false
otherwise.
The stuff in brackets before malloc(...) is an example of a cast
operator. What it does is force C to convert the results of the value on the
right into a data type which corresponds to the cast. In the above example
the cast is of type "pointer to a window structure" the code is forcing C to
convert the pointer being returned by the function "malloc()" to be a Window
pointer. Similarly, if a function varible in a function is floating point,
and it is desired to force that value to integer for the purposes of a given
expression then it can be casted into that type. An example is,
int x,y,z;
float a,b;
x = 10;
a = 2.5;
b = x / a; /* results in b = 4 */
b = x / (int) a; /* results in b = 5 */
It is obvious where cast operators could be useful.
The next set of operators are fairly straightforward, and can be handled
quickly. These are the binary operators. The first set of these are the
operators *, /, %, +, and - which perform the functions of multiplication,
division, modulos, addition, and subtraction respectively. So 'a+b' will
re